use std::fmt::Display;
use std::fs::{self, File};
use std::io::{Error, Read};

#[derive(Debug)]
enum ReadUsernameError {
    IoError(Error),
    EmptyUsername(String),
}

impl std::error::Error for ReadUsernameError {}

impl Display for ReadUsernameError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::IoError(e) => write!(f, "IO error: {e}"),
            Self::EmptyUsername(filename) => write!(f, "Found no username in {filename}"),
        }
    }
}

impl From<Error> for ReadUsernameError {
    fn from(value: Error) -> Self {
        ReadUsernameError::IoError(value)
    }
}

fn read_username(path: &str) -> Result<String, ReadUsernameError> {
    let mut username = String::with_capacity(100);
    File::open(path)?.read_to_string(&mut username)?;
    if username.is_empty() {
        return Err(ReadUsernameError::EmptyUsername(String::from(path)));
    }
    Ok(username)
}

fn main() {
    fs::write("config.dat", "");
    let username = read_username("config.dat");
    println!("username or error: {username:?}");
}
